#include "elog.h"

#include <sys/time.h>

#define gettid() syscall(__NR_gettid)
//#define PRINT_DEVICE    "/dev/kmsg"
#define PRINT_DEVICE    "/dev/ttyMSM0"
#define TAG		"elog"
#define MAX_IPADDR_NAME           32

uint8_t HEX_DUMP = 0;   //用于打开和关闭打印信息


static int g_shmid;
static User_FuncSet* g_UserFunc=NULL;

/* EasyLogger object */
static EasyLogger *elog;
/*fp of elog_output.txt*/
//static FILE *fp = NULL;
static int printDeviceID = -1;
static pthread_mutex_t Output_lock;
/* log buffer */
static char log_buf[ELOG_BUF_SIZE] = { 0 };
/* log tag */
#ifdef DEBUG
static const char *log_tag = "elog";
#endif
/* level output info */
static const char *level_output_info[] =
{
    "A/",
    "E/",
    "W/",
    "I/",
    "D/",
    "V/",
};
/* the output lock enable or disable. default is enable */
static bool output_lock_enabled = false;
/* the output is locked before enable. */
static bool output_is_locked_before_enable = false;
/* the output is locked before disable. */
static bool output_is_locked_before_disable = false;
static void output_lock(void);
static void output_unlock(void);
static void sharedLock_lock(bool f_lock);

static bool get_fmt_enabled(uint8_t level, size_t set);

static void EL_Mutex_Init(pthread_mutex_t *pMutex, char const *name);

/* EasyLogger assert hook */
void (*elog_assert_hook)(const char* expr, const char* func, size_t line);


FILE * gettcufd()
{
    FILE *fd = fopen("/dev/ttyMSM0","a");
    return fd;
}

void printRawData( uint8_t level, const char *tag,const char *head,UCHAR  const * data, int len)
{

    int i;
    char *p;
    char *buffer;
    int bufferSize = 3 * (len + 1) +  (len/16) ;
//    if (NULL == data || len <= 0 || bufferSize > 400)
//    {
//		return;
//    }
    buffer = (char*)malloc(bufferSize);
    if(!buffer) 
    {
        //LOGE(TAG, "malloc print buffer %d bytes error!", bufferSize);
        return;
    }
    p = buffer;
    memset(p, 0, bufferSize);
    
    for(i=0; i < len; i++)
    {
        if(i % 16 == 0 && i != 0)
        {
            // *p = '\r\n';
            strcpy(p, "\r\n"); // 使用 strcpy 添加换行符
            p += strlen("\r\n");
            p++;
            
        }
        sprintf(p, "%02X ", data[i]);
        p += 3;
        
    }
    
    
    if(HEX_DUMP)
    {
        printf("%s",head);
        printf("%s\r\n \r\n", buffer);
    	switch(level)
    	{
    	case ELOG_LVL_ERROR:
    		LOGE(tag, "RAW:%s%s\n", head,buffer);
    		break;
    	case ELOG_LVL_WARN:
    		LOGW(tag, "RAW:%s%s\n", head, buffer);
    		break;
    	case ELOG_LVL_INFO:
    		LOGI(tag, "RAW:%s%s\n", head,buffer);
    		break;
    	case ELOG_LVL_DEBUG:
    		LOGD(tag, "RAW:%s%s\n", head,buffer);
    		break;
    	default:
    		
    		break;
    	}
    }
    //LOGE(TAG, "%s \n", buffer);
    //printf("raw:%s \n", buffer);
    free(buffer);

}



/***********************************************************************************************
Fuction: 		Get LogConfigure_ShareMemory
Description: 	Creat and delete share memory
Calls:		    Null
Called By:	    Init_Log_Configure
Input:		    Null
Output:		    Null
Return:		    shm
Others:		    Null
***********************************************************************************************/
void * Get_LogConfigure_ShareMemory(size_t size, int *shmid)
{
    void *shm = NULL;   
    assert(shmid != NULL);
    *shmid = -1;        
    *shmid = shmget((key_t)ELOG_CONFIGURE_SHM_KEY, size, 0666 | IPC_CREAT);//得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符

    if(*shmid != -1)
    {
        shm = shmat(*shmid, 0, 0);//连接共享内存标识符为shmid的共享内存，连接成功后把共享内存区对象映射到调用进程的地址空间，随后可像本地空间一样访问
        if(shm == (void*)-1)

        {
            return NULL;
        }
    }
    return shm;
}

void Delete_Configure_ShareMemory(void *shm, int shmid)
{
    if(shmdt(shm) == -1)
    {
        fprintf(stderr, "shmdt failed\n");
    }

    if(shmctl(shmid, IPC_RMID, 0) == -1)

    {
        fprintf(stderr, "shmctl(IPC_RMID) failed\n");
    }
}


/***********************************************************************************************
Fuction: 		Get LogConfigure_ShareMemory
Description: 	Creat and delete share memory
Calls:		    Null
Called By:	    Init_Log_Configure
Input:		    Null
Output:		    Null
Return:		    shm
Others:		    Null
***********************************************************************************************/
void Save_LogLevel_Configure(uint8_t level)
{
    FILE *file;
    file = fopen(ELOG_CONFIGURE_FILE_PATH, "wb+");

    if(file)
    {
        fwrite(&level, sizeof(level), 1, file);
		fflush(file);
		fsync(fileno(file));
        fclose(file);
    }
}

uint8_t Get_LogLevel_Configure()
{
    FILE *file;
    uint8_t level = ELOG_LVL_INFO;
	int ret = 0;
    //uint8_t level = ELOG_LVL_DEBUG;

    file = fopen(ELOG_CONFIGURE_FILE_PATH, "r");
    if (file)
    {
        ret = fread(&level, sizeof(level), 1, file);
        fclose(file);
    }
    return level;
}


ElogErrCode elog_init(void)//创建了共享内存
{
    ElogErrCode result = ELOG_NO_ERR;
	if(output_lock_enabled)
  	  EL_Mutex_Init(&Output_lock, "output lock");//初始化 Output_lock锁
    elog = NULL;
    elog = (EasyLogger *)Get_LogConfigure_ShareMemory(sizeof(EasyLogger), &g_shmid);//创建了共享内存
    if(!elog)
    {
        elog = (EasyLogger *)malloc(sizeof(EasyLogger));
		 printf("\ncreate  ShareMemory error!\n");
    }
    ELOG_ASSERT(elog != NULL);
	
	result=1;
	 

    return result;
}

/**
 * EasyLogger start after initialize.
 */
void elog_start(void)
{
    /* enable output */
    elog_set_output_enabled(false);
    /* show version */
   // #ifdef DEBUG
   // elog_i(log_tag, "EasyLogger V%s is initialize success.", ELOG_SW_VERSION);
  //  #endif
}

/**
 * set output enable or disable
 *
 * @param enabled TRUE: enable FALSE: disable
 */
void elog_set_output_enabled(bool enabled)
{
    ELOG_ASSERT((enabled == false) || (enabled == true));
	sharedLock_lock(true);
    printDeviceID = open(PRINT_DEVICE, O_RDWR|O_NOCTTY|O_NDELAY);
    elog->output_enabled = enabled;
	sharedLock_lock(false);
}

/**
 * get output is enable or disable
 *
 * @return enable or disable
 */
bool elog_get_output_enabled(void)
{
	bool value=0;
	sharedLock_lock(true);	
	value=elog->output_enabled;
	sharedLock_lock(false);
	return value;
}

/**
 * set log output format. only enable or disable
 *
 * @param level level
 * @param set format set
 */
void elog_set_fmt(uint8_t level, size_t set)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
	sharedLock_lock(true);
    elog->enabled_fmt_set[level] = set;
	sharedLock_lock(false);
}

/**
 * set log filter all parameter
 *
 * @param level level
 * @param tag tag
 * @param keyword keyword
 */
void elog_set_filter(uint8_t level, const char *tag, const char *keyword)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);

    elog_set_filter_lvl(level);
    elog_set_filter_tag(tag);
    elog_set_filter_kw(keyword);
}

/**
 * set log filter's level
 *
 * @param level level
 */
void elog_set_filter_lvl(uint8_t level)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
	sharedLock_lock(true);
    elog->filter.level = level;
	sharedLock_lock(false);
}

void elog_get_filter_lvl(uint8_t* level)
{
    //ELOG_ASSERT(*level <= ELOG_LVL_VERBOSE);
	sharedLock_lock(true);
    *level=elog->filter.level;
	sharedLock_lock(false);
}
/**
 * set log filter's tag
 *
 * @param tag tag
 */
void elog_set_filter_tag(const char *tag)
{
	sharedLock_lock(true);
    strncpy(elog->filter.tag, tag, ELOG_FILTER_TAG_MAX_LEN);
	sharedLock_lock(false);
}

void elog_get_filter_tag( char *tag)
{
	sharedLock_lock(true);
    strncpy(tag,elog->filter.tag,ELOG_FILTER_TAG_MAX_LEN);
	sharedLock_lock(false);
}
/**
 * set log filter's keyword
 *
 * @param keyword keyword
 */
void elog_set_filter_kw(const char *keyword)
{
	sharedLock_lock(true);	
    strncpy(elog->filter.keyword, keyword, ELOG_FILTER_KW_MAX_LEN);
	sharedLock_lock(false);
}
void elog_get_filter_kw( char *keyword)
{
	sharedLock_lock(true);	
    strncpy( keyword, elog->filter.keyword,ELOG_FILTER_KW_MAX_LEN);
	sharedLock_lock(false);
}

/**
 * output RAW format log
 *
 * @param format output format
 * @param ... args
 */
void elog_raw(const char *format, ...)
{
    va_list args;
    int fmt_result;
	bool value=0;
	sharedLock_lock(true);	
	value=elog->output_enabled;
	sharedLock_lock(false);
    /* check output enabled */
    if (!value)
    {
        return;
    }

    /* args point to the first variable parameter */
    va_start(args, format);

    /* lock output */
    output_lock();

    /* package log data to buffer */
    fmt_result = vsnprintf(log_buf, ELOG_BUF_SIZE, format, args);

    /* output converted log */
    if ((fmt_result > -1) && (fmt_result <= ELOG_BUF_SIZE))
    {
        /* output log */
        elog_port_output(ELOG_LVL_DEBUG,log_buf, fmt_result);
    }
    else
    {
        /* output log */
        elog_port_output(ELOG_LVL_DEBUG,log_buf, ELOG_BUF_SIZE);
    }

    /* unlock output */
    elog_port_output_unlock();

    va_end(args);
}

/**
 * output the log
 *
 * @param level level
 * @param tag tag
 * @param file file name
 * @param func function name
 * @param line line number
 * @param format output format
 * @param ... args
 *
 */
void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
                 const long line, const char *format, ...)
{
    size_t tag_len = strlen(tag), log_len = 0, newline_len = strlen(ELOG_NEWLINE_SIGN);
    char line_num[ELOG_LINE_NUM_MAX_LEN + 1] = { 0 };
    char tag_sapce[ELOG_FILTER_TAG_MAX_LEN / 2 + 1] = { 0 };
    va_list args;
    int fmt_result;
    bool bOutput = false;

    /*
        added by liuxingh@szlanyou.com end
    */

    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);

	sharedLock_lock(true);


    /* level filter */
    if (level > elog->filter.level)
    {
    	sharedLock_lock(false);
        return;
    }
#ifdef DBG_ALL
    if (!strstr(tag, elog->filter.tag)&&strcmp(elog->filter.tag, TAG_NONE))
    {
        bOutput = false;
    }
    else
    {
        bOutput = true;
    }
#else
    #ifdef DBG_TSP
    if (strstr(tag, SERVER_FOURG_TAG))
    {
        bOutput = true;
    }
    #endif
    #ifdef DBG_FOURG
    if (strstr(tag, MCU_FOURG_TAG))
    {
        bOutput = true;
    }
    #endif
    #ifdef DBG_SLEEP
    if (strstr(tag, FOURG_SLEEP_TAG))
    {
        bOutput = true;
    }
    #endif    
    #ifdef DBG_UPGRADE
    if (strstr(tag, UPGRADE_TAG))
    {
        bOutput = true;
    }
    #endif
    #ifdef DBG_DATACONN
    if (strstr(tag, DATACONN_TAG))
    {
        bOutput = true;
    }
    #endif
#endif
	sharedLock_lock(false);
    if(bOutput == false)
    {
        return;
    }
    /* args point to the first variable parameter */
    va_start(args, format);

    /* lock output */
    output_lock();
    /* package level info */
    if (get_fmt_enabled(level, ELOG_FMT_LVL))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]);
    }
    /* package tag info */
    if (get_fmt_enabled(level, ELOG_FMT_TAG))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, tag);
        /* if the tag length is less than 50% ELOG_FILTER_TAG_MAX_LEN, then fill space */
        if (tag_len <= ELOG_FILTER_TAG_MAX_LEN / 2)
        {
            memset(tag_sapce, ' ', ELOG_FILTER_TAG_MAX_LEN / 2 - tag_len);
            log_len += elog_strcpy(log_len, log_buf + log_len, tag_sapce);
        }
        log_len += elog_strcpy(log_len, log_buf + log_len, " ");
    }
    /* package time, process and thread info */
    if (get_fmt_enabled(level, ELOG_FMT_TIME | ELOG_FMT_P_INFO | ELOG_FMT_T_INFO))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, "[");
        /* package time info */
        if (get_fmt_enabled(level, ELOG_FMT_TIME))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_time());
            if (get_fmt_enabled(level, ELOG_FMT_P_INFO | ELOG_FMT_T_INFO))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");
            }
        }
        /* package process info */
        if (get_fmt_enabled(level, ELOG_FMT_P_INFO))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_p_info());
            if (get_fmt_enabled(level, ELOG_FMT_T_INFO))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");
            }
        }
        /* package thread info */
        if (get_fmt_enabled(level, ELOG_FMT_T_INFO))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_t_info());
        }
        log_len += elog_strcpy(log_len, log_buf + log_len, "] ");
    }
    /* package file directory and name, function name and line number info */
    if (get_fmt_enabled(level, ELOG_FMT_DIR | ELOG_FMT_FUNC | ELOG_FMT_LINE))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, "(");
        /* package directory info */
        if (get_fmt_enabled(level, ELOG_FMT_DIR))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, file);
            if (get_fmt_enabled(level, ELOG_FMT_FUNC))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");
            }
            else if (get_fmt_enabled(level, ELOG_FMT_LINE))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, ":");
            }
        }
        /* package function info */
        if (get_fmt_enabled(level, ELOG_FMT_FUNC))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, func);
            if (get_fmt_enabled(level, ELOG_FMT_LINE))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, ":");
            }
        }
        /* package linenumber info */
        if (get_fmt_enabled(level, ELOG_FMT_LINE))
        {
            //TODO snprintf\D7\CAԴռ\D3ÿ\C9\C4ܽϸߣ\AC\B4\FD\D3Ż\AF
            snprintf(line_num, ELOG_LINE_NUM_MAX_LEN, "%ld", line);
            log_len += elog_strcpy(log_len, log_buf + log_len, line_num);
        }
        log_len += elog_strcpy(log_len, log_buf + log_len, ")");
    }

    /* add space and colon sign */
    if (log_len != 0)
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, ": ");
    }

    /* package other log data to buffer. '\0' must be added in the end by vsnprintf. */
    fmt_result = vsnprintf(log_buf + log_len, ELOG_BUF_SIZE - log_len - newline_len + 1, format, args);

    va_end(args);

    /* keyword filter */
	sharedLock_lock(true);
    if (!strstr(log_buf, elog->filter.keyword))
    {
        //TODO \BF\C9\D2Կ\BC\C2ǲ\C9\D3\C3KMP\BC\B0\C6\D3\CB\D8ģʽƥ\C5\E4\D7ַ\FB\B4\AE\A3\AC\CC\E1\C9\FD\D0\D4\C4\DC
        /* unlock output */
		sharedLock_lock(false);
        output_unlock();
        return;
    }
	sharedLock_lock(false);
    /* package newline sign */
    if ((fmt_result > -1) && (fmt_result + log_len + newline_len <= ELOG_BUF_SIZE))
    {
        log_len += fmt_result;
        log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);

    }
    else
    {
        /* copy newline sign */
        strncpy(log_buf - newline_len, ELOG_NEWLINE_SIGN, strlen(ELOG_NEWLINE_SIGN));
    }
    
    log_buf[ELOG_BUF_SIZE - 1] = '\0';

    /* output log */
    elog_port_output(level,log_buf, log_len);

    /* unlock output */
    output_unlock();

}

/**
 * get format enabled
 *
 * @param level level
 * @param set format set
 *
 * @return enable or disable
 */
static bool get_fmt_enabled(uint8_t level, size_t set)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
	size_t tmp;
	sharedLock_lock(true);
	tmp=elog->enabled_fmt_set[level];
	sharedLock_lock(false);

    if ( tmp& set)
    {
        return true;
    }
    else
    {
        return false;
    }
}

/**
 * enable or disable logger output lock
 * @note disable this lock is not recommended except you want output system exception log
 *
 * @param enabled true: enable  false: disable
 */
void elog_output_lock_enabled(bool enabled)
{
    output_lock_enabled = enabled;
    /* it will re-lock or re-unlock before output lock enable */
    if (output_lock_enabled)
    {
        if (!output_is_locked_before_disable && output_is_locked_before_enable)
        {
            /* the output lock is unlocked before disable, and the lock will unlocking after enable */
            elog_port_output_lock();
        }
        else if (output_is_locked_before_disable && !output_is_locked_before_enable)
        {
            /* the output lock is locked before disable, and the lock will locking after enable */
            elog_port_output_unlock();
        }
    }
}

/**
 * lock output
 */
static void output_lock(void)
{
    if (output_lock_enabled)
    {
        elog_port_output_lock();
        output_is_locked_before_disable = true;
    }
    else
    {
        output_is_locked_before_enable = true;
    }
}
/**
 * unlock output
 */
static void output_unlock(void)
{
    if (output_lock_enabled)
    {
        elog_port_output_unlock();
        output_is_locked_before_disable = false;
    }
    else
    {
        output_is_locked_before_enable = false;
    }
}

/**
 * Set a hook function to EasyLogger assert. It will run when the expression is false.
 *
 * @param hook the hook function
 */
void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line))
{
    elog_assert_hook = hook;
}



void EL_Mutex_Init(pthread_mutex_t *pMutex, char const *name)
{
    pthread_mutex_init(pMutex, NULL);
}

void EL_Mutex_Lock(pthread_mutex_t *pMutex)
{
    pthread_mutex_lock(pMutex);

}

void EL_Mutex_Unlock(pthread_mutex_t *pMutex)
{
    pthread_mutex_unlock(pMutex);
}
//#define LOG_TO_FILE 0
ElogErrCode elog_port_init(void)
{
    ElogErrCode result = ELOG_NO_ERR;

#ifdef LOG_TO_FILE
//#ifdef 1
    char savePath[128] = {0};
    time_t timep;
    struct tm *p;

    time(&timep);
    p = localtime(&timep);
    if (p == NULL)
    {
        sprintf(savePath, "/tmp/customer2/applog-lanyouApp");
    }
    else
    {
        sprintf(savePath, "/tmp/customer2/applog-lanyouApp-%02d_%02d_%02d:%02d", p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min);
    }
    //printDeviceID = open(savePath, O_RDWR|O_NOCTTY|O_NDELAY|O_CREAT|O_APPEND);
#else
    //printDeviceID = open(PRINT_DEVICE, O_RDWR|O_NOCTTY|O_NDELAY);
    //dup2(printDeviceID,stdout);
#endif
    // if(printDeviceID < 0)
    // {
    //     fprintf(stderr, "open device %s error !\n",PRINT_DEVICE);
    // }
    return result;
}

/**
 * output log port interface
 *
 * @param log output of log
 * @param size log size
 */
void elog_port_output(uint8_t level,const char *log, size_t size)
{
    int i;
    /* output to terminal */
	char *p = (char *)log;
    for(i = size -2; i > 0; --i)
    {
        if(*(p + i) == '\n')
        {
            *(p + i) = ' ';
            break;
        }
    }

	if(size)
	{
		sharedLock_lock(true);
	    if(level <=ELOG_LVL_INFO)
		{
			if(elog->log_len_Save+size<D_LOG_BUFF_ALL_MAX-1)
			{
				memcpy(&elog->log_buf_Save[elog->log_len_Save],log,size);
				elog->log_len_Save+=size;
			}
		}
		else
		{
			if(elog->log_len+size<D_LOG_BUFF_ALL_MAX-1)
			{
				memcpy(&elog->log_buf_Print[elog->log_len],log,size);
				elog->log_len+=size;
			}
		 }
		sharedLock_lock(false);
	}

   
}

/**
 * output lock
 */
void elog_port_output_lock(void)
{
	EL_Mutex_Lock(&Output_lock);
}

/**
 * output unlock
 */
void elog_port_output_unlock(void)
{
	EL_Mutex_Unlock(&Output_lock);
}

/**
 * get current time interface
 *
 * @return current time
 */
const char *elog_port_get_time(void)
{
    static char cur_system_time[24] = { 0 };
    time_t timep;
    struct tm *p;

    struct timeval tv;  
    gettimeofday(&tv,NULL);  /* 可以精确到毫秒 */

    //time(&timep); /* 返回1970-1-1, 00:00:00以来经过的秒数 */
    timep = tv.tv_sec;
    p = localtime(&timep);
    if (p == NULL)
    {
        return "";
    }
   
    snprintf(cur_system_time, 19, "%02d-%02d %02d:%02d:%02d.%03ld", p->tm_mon + 1, p->tm_mday,
             p->tm_hour, p->tm_min, p->tm_sec,tv.tv_usec/1000);

    return cur_system_time;
}

/**
 * get current process name interface
 *
 * @return current process name
 */
const char *elog_port_get_p_info(void)
{
    static char cur_process_info[10] = { 0 };

    snprintf(cur_process_info, 10, "pid:%04d", getpid());

    return cur_process_info;
}

/**
 * get current thread name interface
 *
 * @return current thread name
 */
const char *elog_port_get_t_info(void)
{
    static char cur_thread_info[10] = { 0 };
     snprintf(cur_thread_info, 10, "tid:%ld", gettid());
   // snprintf(cur_thread_info, 10, "tid:%lu", pthread_self()->tid);

    return cur_thread_info;
}


size_t elog_strcpy(size_t cur_len, char *dst, const char *src)
{
    const char *src_old = src;
    while (*src != 0)
    {
        /* make sure destination has enough space */
        if (cur_len++ <= ELOG_BUF_SIZE)
        {
            *dst++ = *src++;
        }
        else
        {
            break;
        }
    }
    return src - src_old;
}


void elog_port_PrintData()
{
	static  int iError = 0;
	unsigned int iFileNum = 0;
	char tmp[D_LOG_BUFF_ALL_MAX]={0};
	if( 1 )
	{
		sharedLock_lock(true);
		iFileNum=elog->log_len;
		if(iFileNum)
		{
            if (elog->output_enabled == true)
            {
                write(printDeviceID, elog->log_buf_Print, iFileNum);
            }
            elog->log_len=0;
		}

		iFileNum=elog->log_len_Save;
		if(iFileNum)
		{
            if (elog->output_enabled == true)
            {
                printf( "%s\n",elog->log_buf_Save);
               // write(printDeviceID, elog->log_buf_Save, iFileNum);
            }
            memcpy(tmp,elog->log_buf_Save, iFileNum);
            elog->log_len_Save=0;
			 
		}
		sharedLock_lock(false);
		
		if(iFileNum)
		{
			//printf( "print log:%d!!!\n",iFileNum);	
			if(g_UserFunc)
			{
				g_UserFunc->pfSysLogWriteFile(tmp,iFileNum);
			}
		}
	 }
	else
	{
		if(iError<10)
			 printf( "printDeviceID<0!!!\n");	
		
		iError++;
	}

}



void  Quit_ShareMemory()
{
    if(shmdt(elog) == -1)//用来断开与共享内存附加点的地址，禁止本进程访问此片共享内存
    {
        fprintf(stderr, "shmdt failed\n");
    }

    if(shmctl(g_shmid, IPC_RMID, 0) == -1)//删除这片共享内存
    {
        fprintf(stderr, "shmctl(IPC_RMID) failed\n");
    }
	pthread_mutex_destroy(&elog->sharedLock);
}


void Elog_Master_Init()
{
	pthread_mutexattr_t ma;
	pthread_mutexattr_init(&ma);
	pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
	pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
	pthread_mutex_init(&elog->sharedLock,&ma);
	/* port initialize */
	elog_port_init();
	 /* set level to the saved configure value */
	elog_set_filter_lvl(Get_LogLevel_Configure());
	
	elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
	elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME | ELOG_FMT_FUNC | ELOG_FMT_LINE);
	elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME | ELOG_FMT_FUNC | ELOG_FMT_LINE);
	elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME | ELOG_FMT_FUNC | ELOG_FMT_LINE);
	elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL  & ~ELOG_FMT_DIR );
	elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL  & ~ELOG_FMT_DIR );
	
	
	/* start EasyLogger */
	elog_start();
}


void Elog_UserFunc_Set(User_FuncSet* pfUser)
{
	g_UserFunc=pfUser;
}


static void sharedLock_lock(bool f_lock)
{

	if(f_lock)
	{
		pthread_mutex_lock(&elog->sharedLock);
	}
	else
	{
		pthread_mutex_unlock(&elog->sharedLock);
	}
}


 void Sys_CtlSet(SYS_CTL_MODE* ctl_mode ,bool beSet)
{
	sharedLock_lock(true);
	if(beSet)
	{
		elog->sys_ctl_share.sys_ctl= *ctl_mode;
	}
	else
	{
		*ctl_mode=elog->sys_ctl_share.sys_ctl;
	}
	sharedLock_lock(false);
}

 void Sys_xCallStatusSet(char * xCallStatus ,bool beSet)
{
	sharedLock_lock(true);
	if(beSet)
	{
		elog->sys_ctl_share.xCallStatus= *xCallStatus;
	}
	else
	{
		*xCallStatus=elog->sys_ctl_share.xCallStatus;
	}
	sharedLock_lock(false);
}

 
 int do_system_call(const char *fmt, ...)
 {
	 va_list ap;
	 va_list ap_temp;
	 int size = 0;
	 char *command = NULL;
	 FILE *fp = NULL;
 
	 va_start(ap, fmt);
	 va_copy(ap_temp, ap);
	 size = vsnprintf(NULL, 0, fmt, ap_temp);
	 if(size > 0) {
		 command = (char *)malloc(size+1);
		 if(!command) {
			 va_end(ap);
			 //jiangbf 2020-7-27 coverity 4080630
			 va_end(ap_temp);
			 return -1;
		 }
		 vsnprintf(command, size+1, fmt, ap);
	 }
	 va_end(ap);
	 //jiangbf 2020-7-27 coverity 4080630
	 va_end(ap_temp);
	 LOGI(TAG,"system_call:%s",command);
	 //jiangbf 2020-7-27
	 fp = popen(command, "w");
	 if(NULL == fp) {
	 	 //2020-7-27 coverity 4078629
	 	 LOGE(TAG,"do_system_call fail:%s",command);
		 free(command);
		 return -1;
	 }
	 
	 free(command);
	 pclose(fp);
	 return 0;
 }


